home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / gc / GCfinalize.c < prev    next >
C/C++ Source or Header  |  1991-06-04  |  9KB  |  431 lines

  1. /* begincopyright
  2.   Copyright (c) 1988,1990 Xerox Corporation. All rights reserved.
  3.   Use and copying of this software and preparation of derivative works based
  4.   upon this software are permitted. Any distribution of this software or
  5.   derivative works must comply with all applicable United States export
  6.   control laws. This software is made available AS IS, and Xerox Corporation
  7.   makes no warranty about the software, its performance or its conformity to
  8.   any specification. Any person obtaining a copy of this software is requested
  9.   to send their name and post office or electronic mail address to:
  10.     PCR Coordinator
  11.     Xerox PARC
  12.     3333 Coyote Hill Rd.
  13.     Palo Alto, CA 94304
  14.   endcopyright */
  15.  
  16. /*
  17.  * finalize.c
  18.  *
  19.  * PCR finalization.
  20.  * This exports to the PCedar PFinalize interface.
  21.  *
  22.  * Mark Weiser
  23.  * Demers, February 12, 1990 10:43:05 am PST
  24.  * Boehm, March 6, 1990 6:14:46 pm PST
  25.  */
  26.  
  27. #ifdef FINALIZE
  28.  
  29. #include "xr/Errno.h"
  30. #include <xr/GCPrivate.h>
  31. #include <xr/ThreadsMsg.h>
  32.  
  33.  
  34. /*
  35.  * Finalization queues
  36.  */
  37.  
  38. XR_FinalizationQueue
  39. XR_NewFQ ()
  40. {
  41.     XR_FinalizationQueue fq;
  42.  
  43.     fq = (XR_FinalizationQueue)
  44.     XR_malloc(sizeof(struct XR_FinalizationQueueStructure));
  45.     fq->head = NIL;
  46.     fq->tail = NIL;
  47.     XR_InitializeCondition(&(fq->fqNonempty), XR_WAIT_FOREVER);
  48.     XR_EnableAborts(&(fq->fqNonempty));
  49.     return fq;
  50. }
  51.  
  52.  
  53. XR_FinalizationHandle
  54. XR_FQNextNoAbort (fq)
  55.     XR_FinalizationQueue fq;
  56. /*
  57.     Like FQNext, but returns NIL rather than raising aborted.
  58. */
  59. {
  60.     XR_FinalizationHandle h;
  61.  
  62.     if( fq == NIL ) return NIL;
  63.  
  64.     XR_MonitorEntry( &(GC_allocate_ml) );
  65.     while( (h = fq->head) == NIL ) {
  66.     if( XR_WaitCV( &(fq->fqNonempty), &(GC_allocate_ml) ) != 0 ) {
  67.         XR_SetErrno(XR_EABORTED);
  68.         goto Out;
  69.     }
  70.     }
  71.     if( (fq->head = h->next) == NIL ) fq->tail = NIL;
  72.     h->associatedFQ = NIL;
  73.     h->next = NIL;
  74.   Out:
  75.     XR_MonitorExit( &(GC_allocate_ml) );
  76.     return h;
  77. }
  78.  
  79.  
  80. /* ... to be called only from a thread: */
  81.  
  82. static void
  83. XR_RemoveFromFQInternal (h)
  84.     XR_FinalizationHandle h;
  85. {
  86.     XR_FinalizationQueue fq;
  87.     XR_FinalizationHandle p, prev;
  88.  
  89.     fq = h->associatedFQ;
  90.     p = fq->head;
  91.     prev = NIL;
  92.     for(;;) {
  93.     if( p == h ) {
  94.         if( prev == NIL ) fq->head = p->next; else prev->next = p->next;
  95.         if( fq->tail == p ) fq->tail = prev;
  96.         p->next = NIL;
  97.         p->associatedFQ = NIL;
  98.         break;
  99.     }
  100.     if( p == NIL ) XR_Panic("RemoveFromFQInternal 0");
  101.     prev = p;
  102.     p = p->next;
  103.     }
  104. }
  105.  
  106.  
  107. /* ... to be called only from an iop: */
  108.  
  109. static void
  110. XR_InsertOnFQInternal(h)
  111.     XR_FinalizationHandle h;
  112. {
  113.     XR_FinalizationQueue fq;
  114.     XR_FinalizationHandle tl;
  115.  
  116.     fq = h->associatedFQ;
  117.     if( (tl = fq->tail) == NIL ) {
  118.     fq->head = h;
  119.     XR_NakedNotify(&(fq->fqNonempty));
  120.     } else {
  121.         tl->next = h;
  122.     }
  123.     fq->tail = h;
  124.     h->next = NIL;
  125. }
  126.  
  127.  
  128. bool
  129. XR_FQEmpty(fq)
  130.     XR_FinalizationQueue fq;
  131. {
  132.     return ((fq == NIL) || (fq->head == NIL));
  133. }
  134.  
  135.  
  136. /*
  137.  * Controlling finalization of objects
  138.  */
  139.  
  140. XR_FinalizationHandle
  141. XR_NewFinalizationHandle()
  142. {
  143.     register XR_FinalizationHandle h =
  144.         (XR_FinalizationHandle) XR_malloc( sizeof(struct XR_FinalizableObjectStructure) );
  145.     h->firstword = 0;
  146.     h->secondword = 0;
  147.     h->associatedFQ = NIL;
  148.     h->next = NIL;
  149.     return h;
  150. }
  151.  
  152.  
  153. void
  154. XR_EnableFinalization(object, fq, h)
  155.     XR_Pointer object;
  156.     XR_FinalizationQueue fq;
  157.     XR_FinalizationHandle h;
  158. {
  159.     if( (object == NIL) || (fq == NIL) || (h == NIL) ) return;
  160.  
  161.     /* caller gets storage outside the monitor */
  162.     XR_MonitorEntry( &GC_allocate_ml );
  163.     XR_StoreDisguised(object, h);
  164.     h->associatedFQ = fq;
  165.     h->next = GC_finalizeListHead;
  166.     GC_finalizeListHead = h;
  167.     XR_MonitorExit( &GC_allocate_ml );
  168. }
  169.  
  170.  
  171. XR_FinalizationState
  172. XR_DisableFinalization(h)
  173.     XR_FinalizationHandle h;
  174. {
  175.     XR_FinalizationHandle p, prev;
  176.     XR_FinalizationState q;
  177.     word w;
  178.  
  179.     if( h == NIL ) return fzsDisabled;
  180.  
  181.     XR_MonitorEntry( &GC_allocate_ml);
  182.     if( h->associatedFQ == NIL ) {
  183.     q = fzsDisabled;
  184.     } else if( !XR_IsDisguised(h) ) {
  185.     q = fzsOnFQ;
  186.     XR_RemoveFromFQInternal(h);
  187.     } else {
  188.     q = fzsEnabled;
  189.     p = GC_finalizeListHead;
  190.     prev = NIL;
  191.     for(;;) {
  192.         if( p == NIL ) break;
  193.         if( p == h ) {
  194.         if( prev == NIL )
  195.             GC_finalizeListHead = p->next;
  196.         else
  197.             prev->next = p->next;
  198.         break;
  199.         }
  200.         prev = p;
  201.         p = p->next;
  202.     }
  203.     w = XR_FetchFromDisguised(h);
  204.     XR_StoreUndisguised(w,h);
  205.     h->associatedFQ = NIL;
  206.     }
  207.     h->next = NIL;
  208.     XR_MonitorExit( &GC_allocate_ml );
  209.     return q;
  210. }
  211.  
  212.  
  213. XR_FinalizationState
  214. XR_ReenableFinalization(h, fq)
  215.     XR_FinalizationHandle h;
  216.     XR_FinalizationQueue fq;
  217. {
  218.     XR_FinalizationState q;
  219.     word object;
  220.  
  221.     /* arguably the following is incorrect if fq == NIL    */
  222.     /*   but that's a client error anyway.        */
  223.         if( (h == NIL) || (fq == NIL) ) return fzsDisabled;
  224.  
  225.     XR_MonitorEntry( &GC_allocate_ml );
  226.     if( XR_IsDisguised(h) ) {
  227.     q = fzsEnabled;
  228.     } else {
  229.     if( h->associatedFQ == NIL ) {
  230.         q = fzsDisabled;
  231.     } else {
  232.         q = fzsOnFQ;
  233.         XR_RemoveFromFQInternal(h);
  234.     }
  235.     object = XR_FetchFromUndisguised(h);
  236.     XR_StoreDisguised(object,h);
  237.     h->next = GC_finalizeListHead;
  238.     GC_finalizeListHead = h;
  239.     }
  240.     h->associatedFQ = fq;
  241.     XR_MonitorExit( &GC_allocate_ml );
  242.     return q;
  243. }
  244.  
  245.  
  246. XR_FinalizationState
  247. XR_GetFinalizationState(h)
  248.     XR_FinalizationHandle h;
  249. {
  250.     XR_FinalizationState q;
  251.  
  252.     if( h == NIL ) return fzsDisabled;
  253.  
  254.     XR_MonitorEntry( &GC_allocate_ml );
  255.     if( XR_IsDisguised(h) ) {
  256.     q = fzsEnabled;
  257.     } else if( h->associatedFQ != NIL ) {
  258.     q = fzsOnFQ;
  259.     } else {
  260.     q = fzsDisabled;
  261.     }
  262.     XR_MonitorExit( &GC_allocate_ml );
  263.     return q;
  264. }
  265.  
  266.  
  267. XR_Pointer
  268. XR_HandleToObject(h)
  269.     XR_FinalizationHandle h;
  270. {
  271.     word w;
  272.  
  273.     if( h == NIL ) return NIL;
  274.  
  275.     XR_MonitorEntry( &GC_allocate_ml );
  276.     if( XR_IsDisguised(h) ) {
  277.     w = XR_FetchFromDisguised(h);
  278.     } else {
  279.     w = XR_FetchFromUndisguised(h);
  280.     }
  281.     XR_MonitorExit( &GC_allocate_ml );
  282.     return (XR_Pointer)w;
  283. }
  284.  
  285. /*
  286.  *
  287.  * --------- below here, routines are all private to the collector ---------
  288.  *
  289.  */
  290.  
  291.  
  292. static bool
  293. marked(p)
  294.     register struct obj *p;
  295. {
  296.     register struct hblk * h;
  297.     register long word_no;
  298.     register bool result;
  299.     register unsigned long sz;
  300.  
  301.     h = HBLKPTR(p);
  302. #   ifdef INTERIOR_POINTERS
  303.       if (!is_hblk(h)) {
  304.     char m = get_map(h);
  305.     while (m > 0 && m < 0x7f) {
  306.         h -= m;
  307.         m = get_map(h);
  308.     }
  309.       }
  310.       sz = HB_SIZE(h);
  311. #   endif
  312.  
  313.     word_no = WORD_NO(p, h);
  314.     
  315. #   ifdef INTERIOR_POINTERS
  316.        word_no = adjusted_word_no(word_no,sz);
  317. #   endif
  318.  
  319.     result = mark_bit(h, word_no);
  320.     return (result);
  321. }
  322.  
  323.  
  324. static void
  325. mark_through(p)
  326.     char *p;
  327. /*
  328.     Queue everything for marking that p points to, but not p itself.
  329.     Assumes p is a legitimate pointer.
  330. */
  331. {
  332.     unsigned int sz;
  333.     struct hblk * h;
  334.     register long word_no;
  335.  
  336.     h = HBLKPTR(p);
  337. #   ifdef INTERIOR_POINTERS
  338.       if (!is_hblk(h)) {
  339.     char m = get_map(h);
  340.     while (m > 0 && m < 0x7f) {
  341.         h -= m;
  342.         m = get_map(h);
  343.     }
  344.       }
  345. #   endif
  346.  
  347.     word_no = WORD_NO(p, h);
  348.     sz = hb_sz(h);
  349.     if (sz < 0) /* Pointerfree */ return;
  350. #   ifdef INTERIOR_POINTERS
  351.        word_no = adjusted_word_no(word_no,sz);
  352.        p = (char *)h + WORDS_TO_BYTES(word_no);
  353. #   endif
  354.     
  355.     (void)GC_mark_all(p, p+WORDS_TO_BYTES(sz),
  356.     ALIGNMENT, ALL_POINTERS, FALSE /* Dont coerce pointers */);
  357. }
  358.  
  359.  
  360. void
  361. GC_TraceFinalizableObjects()
  362. {
  363.     XR_FinalizationHandle h, prev, next;
  364.     struct obj *p;
  365.  
  366.  
  367.     /*
  368.      * walk down the list, marking everything pointed to,
  369.      * but not (directly) the objects themselves
  370.      */
  371.     if (GC_mark_stack_top != GC_mark_stack_bottom) {
  372.         GC_abort("GC_TraceFinalizableObjects 0");
  373.     }
  374.     for( h = GC_finalizeListHead; h != NIL; h = h->next ) {
  375.     p = (struct obj *) XR_FetchFromDisguised(h);
  376.     if( !marked(p) ) {
  377.         mark_through(p);
  378.         if (XR_verbosity >= XR_VERBOSITY_STATS) {
  379.             GC_mark(ALIGNMENT);
  380.             if (marked(p)) {
  381.                 GC_printf("Finalization cycle involving 0x%X\n", p);
  382.             }
  383.         }
  384.     }
  385.     }
  386.     GC_mark(ALIGNMENT);
  387.  
  388.     /*
  389.      * Find still unmarked objects, mark them,
  390.      *   and put them on finalization queues.
  391.      */
  392.  
  393.     if (GC_mark_stack_top != GC_mark_stack_bottom) {
  394.         GC_abort("GC_TraceFinalizableObjects 1");
  395.     }
  396.     prev = NIL;
  397.     for( h = GC_finalizeListHead; h != NIL; h = next ) {
  398.     next = h->next; /* remember now, because we may throw h away */
  399.     p = (struct obj *) XR_FetchFromDisguised(h);
  400.     if (! marked(p)) {
  401.  
  402.         /* remove from list */
  403.         if (prev != NIL) {
  404.             prev->next = h->next;
  405.         } else {
  406.             GC_finalizeListHead = h->next;
  407.         }
  408.  
  409.         /* put on finalization queue */
  410.         XR_StoreUndisguised(p,h);
  411.         XR_InsertOnFQInternal(h);
  412.  
  413.         /* push the pointer on the mark stack for later */
  414.         if (quicktest(p)) {
  415.             PUSH_MS((word) p);
  416.         }
  417.         /* don't update prev here, since we deleted h */
  418.  
  419.     } else {
  420.  
  421.         prev = h;
  422.  
  423.     }
  424.     } /* done walking list for finalizing */
  425.  
  426.     GC_mark(ALIGNMENT); /* mark finalized objects */
  427. }
  428.  
  429.  
  430. #endif /* FINALIZE */
  431.